#include "SymmetricEncryption.h"

#include <iostream>
#include <openssl/evp.h>
#include <openssl/types.h>

#include "config.h"
#include "timeoperation.h"

bool SymmetricEncryption::aes_Encryption(unsigned char* symmetricKey,
                                         unsigned char* iv,
                                         const unsigned char* plainText,
                                         int plainTextLen,
                                         unsigned char* cipherText,
                                         int* cipherTextLen)
{
    int tmpLen = 0;
    //首先创建加密上下文
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

    //初始化加密参数
    if (!EVP_EncryptInit_ex2(ctx, EVP_aes_256_cbc(), symmetricKey, iv, NULL)) {
        OPERATION_FAIL("EVP_EncryptInit_ex2", "SymmetricEncryption", __FILE__, __LINE__, "");
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    if (!EVP_EncryptUpdate(ctx, cipherText, cipherTextLen, plainText, plainTextLen)) {
        OPERATION_FAIL("EVP_EncryptUpdate", "SymmetricEncryption", __FILE__, __LINE__, "");
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    if (!EVP_EncryptFinal_ex(ctx, cipherText + *cipherTextLen, &tmpLen)) {
        OPERATION_FAIL("EVP_EncryptFinal_ex", "SymmetricEncryption", __FILE__, __LINE__, "");
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }
    *cipherTextLen += tmpLen;

    // OPERATION_SUCCESS(" Encrypting Data ", "SymmetricEncryption", "");

    return true;
}

bool SymmetricEncryption::aes_Decryption(unsigned char* symmetricKey,
                                         const unsigned char* iv,
                                         const unsigned char* cipherText,
                                         int cipherTextLen,
                                         unsigned char* plainText,
                                         int* plainTextLen)
{
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();

    if (!EVP_DecryptInit_ex2(ctx, EVP_aes_256_cbc(), symmetricKey, iv, NULL)) {
        std::cerr << "使用EVP_DecryptInit_ex2函数初始化加密参数失败" << std::endl;
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    if (!EVP_DecryptUpdate(ctx, plainText, plainTextLen, cipherText, cipherTextLen)) {
        std::cerr << "使用EVP_DecryptUpdate解密数据失败" << std::endl;
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    int tmpLen = 0;

    if (!EVP_DecryptFinal_ex(ctx, plainText + *plainTextLen, &tmpLen)) {
        std::cerr << "调用EVP_DecryptFinal解密数据失败" << std::endl;
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }
    *plainTextLen += tmpLen;
    // OPERATION_SUCCESS(" Decrypting Data ", "SymmetricEncryption", "");
    return true;
}
